package com.ruoyi.common.config;

import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.weixinpayscanandride.model.QueryTransactionRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

import static com.ruoyi.common.constant.WXConstants.*;

/**
 * @author cpf
 * @date 2024/2/21 16:31
 * @description 微信支付
 */
@Configuration
public class WxPayConfig {



    /**
     * 初始化config对象，这个对象在构建各种支付执行器对象的时候需要传入，并且可复用
     * @return  RSAAutoCertificateConfig
     */
    @Bean
    public RSAAutoCertificateConfig getMyRSAConfig(){
        return new RSAAutoCertificateConfig.Builder()
                .merchantId(MCH_ID)
                .privateKeyFromPath(KEY_PATH)
                .merchantSerialNumber(MCH_SERIAL_NO)
                .apiV3Key(API_KEY)
                .build();
    }
    

    /*
     * 构建微信支付jsapi执行器对象
     * */
    @Bean
    public JsapiService getJsapiServiceExtension(@Autowired Config config){
        return new JsapiService.Builder().config(config).build();
    }


    /**
     * 发起预支付
     * @param outTradeNo 订单号
     * @param description 描述信息
     * @param totalPrice 订单总价格
     * @param openid 支付人
     * @return PrepayResponse
     */
    public PrepayResponse WxPay(String outTradeNo, String description, BigDecimal totalPrice, String openid) {
        //构建请求参数
        PrepayRequest request = new PrepayRequest();
        //服务商应用ID
        request.setAppid(APP_ID);
        //服务商户号
        request.setMchid(MCH_ID);
        //通知地址 异步接收微信支付结果通知的回调地址，通知URL必须为外网可访问的URL，不能携带参数。 公网域名必须为HTTPS，如果是走专线接入，使用专线NAT IP或者私有回调域名可使用HTTP
        request.setNotifyUrl(NOTIFY_URL);

        //商户订单号
        request.setOutTradeNo(outTradeNo);

        //商品描述信息
        request.setDescription(description);

        //订单金额
        Amount amount = new Amount();
        //单位为分
        BigDecimal bigDecimal = new BigDecimal(100);
        BigDecimal amount1 = totalPrice.multiply(bigDecimal);
        //元向分的转换
        amount.setTotal(amount1.intValue());
        request.setAmount(amount);


        //订单超时时间
        request.setTimeExpire(getDate());

        //支付者
        Payer payer = new Payer();
        payer.setOpenid(openid);
        request.setPayer(payer);

        //【附加数据】 附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用，实际情况下只有支付完成状态才会返回该字段。
        //request.setAttach(req.getOrderType());

        //获取service
        JsapiService service = getJsapiServiceExtension(getMyRSAConfig());
        // 调用下单方法，得到应答
        return service.prepay(request);
    }



    /**
     * 根据订单号查询订单是否支付
     * @param orderNo 订单号
     * @return Transaction
     */
    public Transaction isPay(String orderNo) {
        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
        request.setMchid(MCH_ID);
        request.setOutTradeNo(orderNo);

        JsapiService service = getJsapiServiceExtension(getMyRSAConfig());
        Transaction result = null;
        try {
            result = service.queryOrderByOutTradeNo(request);
            System.out.println(result.getTradeState());
        } catch (ServiceException e) {
            // API返回失败, 例如ORDER_NOT_EXISTS
            System.out.printf("code=[%s], message=[%s]\n", e.getErrorCode(), e.getErrorMessage());
            System.out.printf("reponse body=[%s]\n", e.getResponseBody());
        }
        return result;
    }


    /**
     * 超时时间
     * @return 1
     */
    public static String getDate(){
        // 获取当前时间
        ZonedDateTime currentDateTime = ZonedDateTime.now();

        ZonedDateTime zonedDateTime = currentDateTime.plusMinutes(15);
        // 根据你的需求，创建一个格式器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");

        // 使用格式器将当前时间格式化为字符串

        return zonedDateTime.format(formatter);
    }


}
